/*
 * Albareth - an action roleplaying game.
 * Copyright (C) 2008 Jens Anuth
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 *  02110-1301, USA.
 * 
 * $Id: SpellShootProjectile.java 45 2008-05-14 23:04:29Z jens464 $
*/
package albareth.core.action;

import sun.security.action.GetLongAction;
import frosch.util.Range;
import albareth.core.GameEffect;
import albareth.core.GameEffectObserver;
import albareth.core.entity.Mobile;
import albareth.frontend.Resources;
import albareth.frontend.Tile;
import albareth.util.Location;

public class SpellShootProjectile extends Spell implements GameEffectObserver
{
    private Tile _projectile;
    private String _effectId;
    private boolean _spinning;
    private int _hitFlags;
    private Range _damage;
    private String _shootSoundId = Resources.SOUND_THROW;
    private String _hitSoundId = Resources.SOUND_RANGED_HIT;
    private float _speed = 5f;
    
    private Mobile _caster = null;


    public SpellShootProjectile(String name, Tile projectile, String effectId, boolean spinning,
            Range damage, int hitFlags)
    {
        super(name, projectile);
        _effectId = effectId;
        _projectile = projectile;
        _spinning = spinning;
        _hitFlags = hitFlags;
        _damage = damage;
        setRange(8);
        setFlags(HARMFUL|TARGET_LOC|TARGET_NOSELF);
    }

    protected boolean onExecute(Mobile src)
    {
        boolean damageAlreadyObserved = false;
        if (_projectile != null)
        {
            GameEffect effect = GameEffect.flyingProjectile(
                    _projectile,
                    src.getLocation(),
                    internalTargetLocation,
                    (float)(_speed + getSpellStrength() * .5),
                    _spinning, _hitFlags
            );

            effect.setObserver(this);
            src.emitEffect(effect);
            damageAlreadyObserved = true;
        }
        
        if (_effectId != null)
        {
            GameEffect effect = GameEffect.flying(
                    _effectId,
                    src.getLocation(),
                    internalTargetLocation,
                    (float)(_speed + getSpellStrength() * .5),
                    _spinning, _hitFlags
            );

            if (!damageAlreadyObserved) { //so there is only one damage hit on
                                          //effects with both particle and tile
                effect.setObserver(this);
            }
            src.emitEffect(effect);
        }
        
        src.emitSound(_shootSoundId);
        
        _caster = src;

        return true;
    }

    protected boolean onInitiate(Mobile src)
    {
        return true;
    }

    public void effectFinished(GameEffect effect)
    {
        int projectileDamage = _damage.getRandomValue() + 2 * getSpellStrength();
        int damageType = 0; //TODO: damage type fire
        
        Location hitLoc = effect.getCurrentLocation();
        
        GameEffect hitEffect = GameEffect.stationary(
                Resources.EFFECT_DUST, hitLoc, -1
        );
        _caster.emitEffect(hitEffect);
        
        if (hitLoc.isBlocked()) {
            _caster.emitSound(_hitSoundId);
        }

        
        //direct hit explode cell:
        hitLoc.inflictDamage(
                Math.round(projectileDamage), damageType, _caster);
    }

    public void setShootSoundId(String soundId)
    {
        _shootSoundId = soundId;
    }
    
    public void setHitSoundId(String soundId)
    {
        _hitSoundId = soundId;
    }

    public float getSpeed()
    {
        return _speed;
    }

    public void setSpeed(float speed)
    {
        _speed = speed;
    }

}
